package cn.taskservice.common.utils.assret;

import cn.taskservice.common.exception.ServiceException;
import cn.taskservice.common.exception.ValidationException;

import java.util.*;
import java.util.function.Supplier;

/**
 * 参数断言工具类（生产级）
 * 支持 failFast、链式操作、自定义异常、丰富断言类型
 */
public class AssertUtil {

    private final boolean failFast;
    private final List<Throwable> errors = new ArrayList<>();

    private AssertUtil(boolean failFast) {
        this.failFast = failFast;
    }

    /**
     * 默认开启 failFast
     */
    public static AssertUtil start() {
        return new AssertUtil(true);
    }

    /**
     * 可指定 failFast 模式
     */
    public static AssertUtil start(boolean failFast) {
        return new AssertUtil(failFast);
    }

    private void handleError(Supplier<? extends RuntimeException> exceptionSupplier) {
        if (failFast) {
            throw exceptionSupplier.get();
        } else {
            errors.add(exceptionSupplier.get());
        }
    }

    public AssertUtil isNull(Object obj) {
        String msg = "参数不能为 null";
        return isNull(obj, msg, () -> new ServiceException(msg));
    }

    public AssertUtil isNull(Object obj, String msg) {
        return isNull(obj, msg, () -> new ServiceException(msg));
    }

    public AssertUtil isNull(Object obj, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (obj != null) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notNull(Object obj) {
        String msg = "参数不能为 null";
        return notNull(obj, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notNull(Object obj, String msg) {
        return notNull(obj, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notNull(Object obj, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (obj == null) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil isTrue(boolean condition) {
        String msg = "断言失败，条件不为 true";
        return isTrue(condition, msg, () -> new ServiceException(msg));
    }

    public AssertUtil isTrue(boolean condition, String msg) {
        return isTrue(condition, msg, () -> new ServiceException(msg));
    }

    public AssertUtil isTrue(boolean condition, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (!condition) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notEmpty(Collection<?> collection) {
        String msg = "集合不能为空";
        return notEmpty(collection, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Collection<?> collection, String msg) {
        return notEmpty(collection, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Collection<?> collection, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (collection == null || collection.isEmpty()) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notBlank(String str) {
        String msg = "字符串不能为空或空白";
        return notBlank(str, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notBlank(String str, String msg) {
        return notBlank(str, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notBlank(String str, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (str == null || str.trim().isEmpty()) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notEqual(String a, String b) {
        String msg = "两个字符串不能相等";
        return notEqual(a, b, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEqual(String a, String b, String msg) {
        return notEqual(a, b, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEqual(String a, String b, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (Objects.equals(a, b)) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notEmpty(Map<?, ?> map) {
        String msg = "Map 不能为空";
        return notEmpty(map, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Map<?, ?> map, String msg) {
        return notEmpty(map, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Map<?, ?> map, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (map == null || map.isEmpty()) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notEmpty(Object[] array) {
        String msg = "数组不能为空";
        return notEmpty(array, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Object[] array, String msg) {
        return notEmpty(array, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Object[] array, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (array == null || array.length == 0) {
            handleError(exSupplier);
        }
        return this;
    }

    public AssertUtil notEmpty(Enum<?>[] enums) {
        String msg = "枚举数组不能为空";
        return notEmpty(enums, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Enum<?>[] enums, String msg) {
        return notEmpty(enums, msg, () -> new ServiceException(msg));
    }

    public AssertUtil notEmpty(Enum<?>[] enums, String msg, Supplier<? extends RuntimeException> exSupplier) {
        if (enums == null || enums.length == 0) {
            handleError(exSupplier);
        }
        return this;
    }

    /**
     * 所有校验结束后手动触发（非 failFast 模式下使用）
     */
    public void check() {
        if (!errors.isEmpty()) {
            // 抛出聚合异常，包含所有错误
            throw new ValidationException(errors);
        }
    }
}
